package com.zmn.plat.business.impl.product.item;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.Resource;

import com.google.common.collect.Lists;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.plat.business.interfaces.pilot.ChannelPriceBService;
import com.zmn.plat.business.interfaces.price.ItemPriceBService;
import com.zmn.plat.business.interfaces.price.meter3.MeterFlow3CommonBService;
import com.zmn.plat.business.interfaces.price.meter3.MeterFlow3ItemBService;
import com.zmn.plat.business.interfaces.product.ProductDetailsBService;
import com.zmn.plat.common.dto.price.ItemPriceQuery;
import com.zmn.plat.common.dto.price.ItemTo;
import com.zmn.plat.common.dto.price.meter3.ItemDRO3;
import com.zmn.plat.common.dto.price.meter3.ItemPriceQuery3;
import com.zmn.plat.common.dto.price.meter3.ProductTariffTypeDRO;
import com.zmn.plat.common.dto.price.meter3.ProductTariffTypeQuery;
import com.zmn.plat.common.dto.product.ProductDIO;
import com.zmn.plat.common.dto.product.ProductSimpleDRO;
import com.zmn.plat.common.dto.product.base.ProductBaseDRO;
import com.zmn.plat.common.dto.product.item.*;
import com.zmn.plat.common.dto.product.item.group.ItemGroupDRO;
import com.zmn.plat.model.entity.pilot.SupportPilotVO;
import com.zmn.plat.model.entity.service.category.ItemCategory;
import com.zmn.plat.model.entity.service.tariff.ServiceTariff;
import com.zmn.plat.services.interfaces.service.category.ItemCategoryService;
import com.zmn.plat.services.interfaces.service.tariff.ServiceTariffService;
import com.zmn.plat.utils.bean.BeanCopyUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.plat.business.interfaces.product.ProductBService;
import com.zmn.plat.business.interfaces.product.item.ItemBService;
import com.zmn.plat.business.interfaces.product.tariff.TariffProductBService;
import com.zmn.plat.business.interfaces.product.tariff.item.ProductServiceItemPriceBService;
import com.zmn.plat.business.interfaces.servcategory.ShowCategoryAssociationBService;
import com.zmn.plat.business.interfaces.service.item.ServiceItemBService;
import com.zmn.plat.common.constant.OnePriceConsts;
import com.zmn.plat.common.constant.ProductConsts;
import com.zmn.plat.common.dictionary.PlatErrorCodeDict;
import com.zmn.plat.common.dto.product.pricelist.ProductPriceListDRO;
import com.zmn.plat.common.dto.service.item.ProductServiceItemDRO;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.manager.dictionary.ProductDict;
import com.zmn.plat.model.entity.product.ServProduct;
import com.zmn.plat.model.entity.servcategory.ShowCategoryAssociationVO;
import com.zmn.plat.model.entity.service.item.ServiceItem;
import com.zmn.plat.model.vo.product.tariff.item.BaseTariffGroupItemPriceVo;
import com.zmn.plat.model.vo.product.tariff.item.price.ProductServiceItemExcutePriceQueryVo;
import com.zmn.plat.model.vo.product.tariff.item.price.ProductServiceItemExcutePriceResultVo;
import com.zmn.plat.services.interfaces.product.ServProductService;
import com.zmn.plat.services.interfaces.service.item.ServiceItemService;
import com.zmn.plat.services.interfaces.service.item.config.ServiceItemTimeConfigService;

import lombok.extern.slf4j.Slf4j;

/**
 * 描述: 服务项BService
 *
 * @author : tanghongjun
 * @since 2020年3月31日10:28:15
 */
@Service
@Slf4j
public class ItemBServiceImpl implements ItemBService {

    @Resource
    ChannelPriceBService channelPriceBService;
    @Resource
    TariffProductBService tariffProductBService;
    @Resource
    ServProductService servProductService;
    @Resource
    ServiceItemBService faultItemBService;
    @Resource
    ServiceItemService faultItemService;
    @Resource
    ProductBService productBService;
    @Resource
    ItemPriceBService itemPriceBService;
    @Resource
    MeterFlow3ItemBService meterFlow3ItemBService;
    @Resource
    ShowCategoryAssociationBService showCategoryAssociationBService;
    @Resource
    private ServiceItemTimeConfigService faultItemTimeConfigService;
    @Resource
    ProductServiceItemPriceBService productFaultItemPriceBService;
    @Resource
    ProductDetailsBService productDetailsBService;
    @Resource
    ServiceTariffService serviceTariffService;
    @Resource
    MeterFlow3CommonBService meterFlow3CommonBService;
    @Resource
    ItemCategoryService itemCategoryService;

    @Override
    public ProductPriceListDRO getProductPriceListByDIO(ItemDIO itemDIO) throws PlatException {
        if (Objects.isNull(itemDIO) || Objects.isNull(itemDIO.getChannelId()) || Objects.isNull(itemDIO.getCityId()) || Objects.isNull(itemDIO.getProductId())
            || Objects.isNull(itemDIO.getBizType())) {
            log.error("listItemByDIO 参数合法：{}", itemDIO);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        ProductDIO productDIO = new ProductDIO();
        productDIO.setProductId(itemDIO.getProductId());
        // 查询产品基础信息 修改了查询逻辑 2021-11-17 17:52:59
        List<ProductBaseDRO> servProductList = productDetailsBService.listBaseDROByDIO(productDIO);

        if (CollectionUtil.isNullOrEmpty(servProductList)) {
            log.error("product not exist error");
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SHOW_PRODUCT_NOT_EXIST);
        }

        ProductBaseDRO productBaseDRO = servProductList.get(0);
        ServProduct servProduct = new ServProduct();
        BeanUtils.copyProperties(productBaseDRO, servProduct);

        ProductPriceListDRO productPriceListDRO = new ProductPriceListDRO();
        productPriceListDRO.setProductId(productBaseDRO.getProductId());
        productPriceListDRO.setProductName(productBaseDRO.getName());
        productPriceListDRO.setCategName(productBaseDRO.getCategName());
        productPriceListDRO.setServCategName(productBaseDRO.getServCategName());

//        if (checkSupportTariff(servProduct, itemDIO)) {
//            productPriceListDRO.setSupportQuotation(GlobalConsts.YES);
//            itemDIO.setTariffType(ProductDict.TRIFF_TYPE_TARIFF);
//        } else {
//            itemDIO.setTariffType(ProductDict.TRIFF_TYPE_SERVICE);
//        }
//        List<ItemDRO> itemDROS = listItemByProductAndDIO(servProduct, itemDIO);

        // 查询价格表类型
        Integer tariffType;
        Integer tariffId = itemDIO.getTariffId();
        if (NumberUtil.isNullOrZero(tariffId)) {
            ProductTariffTypeQuery typeQuery = new ProductTariffTypeQuery();
            BeanCopyUtils.copyProperties(itemDIO, typeQuery);
            typeQuery.setProductIdList(Arrays.asList(itemDIO.getProductId()));
            List<ProductTariffTypeDRO> typeDROS = meterFlow3CommonBService.listProductTariffTypeByQuery(typeQuery);
            tariffType = typeDROS.get(0).getTariffType();
        } else {
            ServiceTariff tariff = serviceTariffService.findByKeyWithCache(tariffId);
            tariffType = Objects.isNull(tariff) ? null : tariff.getTariffType();
        }

        List<ItemDRO> itemDROS = new ArrayList<>();
        if (Objects.equals(ProductDict.TRIFF_TYPE_TARIFF3, tariffType)) {
            // 走计价器3.0
            ItemPriceQuery3 itemPriceQuery3 = new ItemPriceQuery3();
            BeanCopyUtils.copyProperties(itemDIO, itemPriceQuery3);
            List<ItemDRO3> itemDRO3s = meterFlow3ItemBService.listItemPriceTransByQuery(itemPriceQuery3);

            // 故障类型排序Map
//            List<Integer> categIdList = itemDRO3s.stream().map(m -> m.getItemCategId()).distinct().collect(Collectors.toList());
//            Map<Integer, Integer> categSortMap = Optional.ofNullable(itemCategoryService.listByKeys(categIdList))
//                    .orElse(Collections.emptyList())
//                    .stream()
//                    .collect(Collectors.toMap(ItemCategory::getCategId, ItemCategory::getSort));
            for (ItemDRO3 itemTo : itemDRO3s) {
                ItemDRO itemDRO = new ItemDRO();
                BeanCopyUtils.copyProperties(itemTo, itemDRO);
                itemDRO.setBackProductCategTwoId(itemTo.getCategId());
                itemDRO.setBackProductCategTwoSort(itemTo.getCategSort());
                itemDRO.setFaultCategName(itemTo.getItemCategName());
                itemDRO.setFaultCategId(itemTo.getItemCategId());
//                itemDRO.setCategSort(categSortMap.get(itemTo.getItemCategId()));
                itemDRO.setItemStatus(GlobalConsts.YES);
                itemDROS.add(itemDRO);
            }
        } else {
            // 走非计价器3.0
            ItemPriceQuery query = new ItemPriceQuery();
            BeanCopyUtils.copyProperties(itemDIO, query);
            List<ItemTo> itemTos = itemPriceBService.listItemPriceTransByQuery(query);
            for (ItemTo itemTo : itemTos) {
                ItemDRO itemDRO = new ItemDRO();
                BeanCopyUtils.copyProperties(itemTo, itemDRO);
                itemDRO.setBackProductCategTwoId(itemTo.getCategId());
                itemDRO.setBackProductCategTwoSort(itemTo.getCategSort());
                itemDRO.setFaultCategName(itemTo.getItemCategName());
                itemDRO.setFaultCategId(itemTo.getItemCategId());
                itemDRO.setCategSort(itemTo.getItemCategSort());
                itemDRO.setItemStatus(GlobalConsts.YES);
                itemDROS.add(itemDRO);
            }
        }

        if (CollectionUtil.isNullOrEmpty(itemDROS)) {
            log.error("item not exist error");
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PRODUCT_ITEM_NULL);
        }

        productPriceListDRO.setRemark(itemDROS.get(0).getSpecialDesc());

        // 如果是后台产品
        if (Objects.equals(productBaseDRO.getShowType(), ProductConsts.ERP_PRODUCT_TYPE)) {
            List<ItemGroupDRO> itemGroupDROList = new ArrayList<>();

            Map<Integer, List<ItemDRO>> collect = itemDROS.stream().filter(itemDRO -> Objects.equals(itemDRO.getItemStatus(), GlobalConsts.YES))
                .sorted(Comparator.comparing(ItemDRO::getGroupSort))
                .collect(Collectors.groupingBy(ItemDRO::getGroupId, LinkedHashMap::new, Collectors.toList()));

            itemDROS.stream().findAny().ifPresent(itemDRO -> productPriceListDRO.setRemark(itemDRO.getDesc()));

            collect.forEach((groupId, itemDROList) -> {
                // 处理最内层
                List<ItemPriceSimpleDRO> servItems =
                    itemDROList.stream().filter(itemDRO -> Objects.equals(itemDRO.getItemStatus(), GlobalConsts.YES))
                            .sorted(Comparator.comparing(ItemDRO::getItemSort))
                            .map(servServiceItemDRO -> new ItemPriceSimpleDRO(servServiceItemDRO.getItemId(),
                        servServiceItemDRO.getItemName(), servServiceItemDRO.getPrice(),
                                                                              servServiceItemDRO.getBrief(),
                                                                              servServiceItemDRO.getItemDesc(),
                                                                              servServiceItemDRO.getUnit(), null)).collect(Collectors.toList());
                // 处理中间层
                ItemDRO itemDRO = itemDROList.get(itemDROList.size() - 1);
                String groupName = itemDRO.getGroupName();
                ItemGroupDRO priceVO = new ItemGroupDRO(groupId, groupName, servItems);
                itemGroupDROList.add(priceVO);
            });
            productPriceListDRO.setItemGroupDROList(itemGroupDROList);
        } else {
            List<ItemGroupDRO> itemGroupDROList = getQuotationServiceItem(itemDROS);
            productPriceListDRO.setItemGroupDROList(itemGroupDROList);
        }

        return productPriceListDRO;
    }

    @Override
    public List<ItemDRO> listItemByDIO(ItemDIO itemDIO) throws PlatException {
        log.info("listItemByDIO 参数为：{}", itemDIO);
        // 兼容处理，后期删除
        if (NumberUtil.isPositiveInteger(itemDIO.getType()) && NumberUtil.isNullOrZero(itemDIO.getBizType())) {
            itemDIO.setBizType(itemDIO.getType());
        }

        if (Objects.isNull(itemDIO) || Objects.isNull(itemDIO.getChannelId()) || Objects.isNull(itemDIO.getCityId()) || Objects.isNull(itemDIO.getProductId())
            || Objects.isNull(itemDIO.getBizType())) {
            log.error("listItemByDIO 参数合法：{}", itemDIO);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        ServProduct servProduct = servProductService.findByKeyWithCache(itemDIO.getProductId());

        return listItemByProductAndDIO(servProduct, itemDIO);
    }

    @Override
    public List<ItemPriceDRO> listTotalPriceByDIO(List<ItemPriceDIO> list) {
        if (CollectionUtils.isEmpty(list)) {
            log.error("listTotalPriceByDIO param is :{}", list);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        Map<Integer, ItemPriceDRO> paramMap = new HashMap<>(list.size());
        BeanCopier copier = BeanCopier.create(ItemPriceDIO.class, ItemPriceDRO.class, false);
        for (ItemPriceDIO dio : list) {
            ItemPriceDRO dro = new ItemPriceDRO();
            copier.copy(dio, dro, null);
            paramMap.put(dro.getItemId(), dro);
        }
        // 原始数据用于获取阶梯
        List<ServiceItem> faultItems = faultItemService.listByItemIds(new ArrayList<>(paramMap.keySet()));
        if (CollectionUtils.isEmpty(faultItems)) {
            log.error("listItemByDIO 参数合法：{},errorCode:{}", list, PlatErrorCodeDict.ERROR_CODE_PRODUCT_ITEM_NOT_EXIT);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PRODUCT_ITEM_NOT_EXIT);
        }
        BeanCopier copierPrice = BeanCopier.create(ServiceItem.class, BaseTariffGroupItemPriceVo.class, false);
        for (ServiceItem item : faultItems) {
            ItemPriceDRO dro = paramMap.get(item.getItemId());
            BaseTariffGroupItemPriceVo priceVo = new BaseTariffGroupItemPriceVo();
            copierPrice.copy(item, priceVo, null);
            priceVo.setPrice(dro.getPrice());
            productFaultItemPriceBService.getTotalPrice(priceVo, dro);
        }
        List<ItemPriceDRO> rspList = new ArrayList<>(paramMap.values());
        return rspList;
    }

    private boolean checkSupportTariff(ServProduct servProduct, ItemDIO itemDIO) {
        boolean isTariffChannel = false;

        // 如果是后端产品，转换成前端产品分类
        if (Objects.equals(servProduct.getShowType(), ProductConsts.ERP_PRODUCT_TYPE)) {
            List<ShowCategoryAssociationVO> showCategoryAssociationVOS =
                showCategoryAssociationBService.listByCategoryId(servProduct.getServCategId(), servProduct.getCategOneId(), servProduct.getCategId());
            if (CollectionUtil.isNotNullOrEmpty(showCategoryAssociationVOS)) {
                isTariffChannel = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(itemDIO.getChannelId(), itemDIO.getCityId(), OnePriceConsts.TARIFF,
                        showCategoryAssociationVOS.get(0).getShowServCategId(), showCategoryAssociationVOS.get(0).getShowCategId());
            }
        } else {
            isTariffChannel = channelPriceBService.checkByChannelIdAndCityIdAndTypeAndCateg(itemDIO.getChannelId(), itemDIO.getCityId(), OnePriceConsts.TARIFF, servProduct.getServCategId(),
                servProduct.getCategId());
        }

        if (isTariffChannel) {
            isTariffChannel = productBService.checkTariffByProductIdAndShowType(servProduct, itemDIO.getChannelId(), servProduct.getShowType(), itemDIO.getBizType());
        }

        return isTariffChannel;
    }

    private List<ItemDRO> listItemByProductAndDIO(ServProduct servProduct, ItemDIO itemDIO) throws PlatException {
        ProductServiceItemExcutePriceQueryVo queryVo = new ProductServiceItemExcutePriceQueryVo();

        if (Objects.isNull(itemDIO.getFilterBizType()) || itemDIO.getFilterBizType()) {
            queryVo.setFilterBizType(true);
        } else {
            queryVo.setFilterBizType(false);
        }

        if (NumberUtil.isPositiveInteger(itemDIO.getTariffType())) {
            queryVo.setTariffType(itemDIO.getTariffType());
        } else {
            queryVo.setTariffType(checkSupportTariff(servProduct, itemDIO) ? ProductDict.TRIFF_TYPE_TARIFF : ProductDict.TRIFF_TYPE_SERVICE);
        }
        queryVo.setPageSize(1000);
        queryVo.setProductId(servProduct.getProductId());
        queryVo.setShowType(servProduct.getShowType());
        queryVo.setChannelId(itemDIO.getChannelId());
        queryVo.setBizType(itemDIO.getBizType());
        queryVo.setBrandId(itemDIO.getBrandId());
        queryVo.setServCategId(servProduct.getServCategId());
        queryVo.setCategOneId(servProduct.getCategOneId());
        queryVo.setCategId(servProduct.getCategId());
        queryVo.setCityId(itemDIO.getCityId());
        queryVo.setDifficultId(itemDIO.getDifficultId());
        List<ProductServiceItemExcutePriceResultVo> productFaultItemExcutePriceResultVos = tariffProductBService.listByExcuteQueryCached(queryVo);
        // 添加时间段限制
        if (!Objects.isNull(itemDIO.getServiceTime())) {
            // 排除在当前时间不显示的项目
            List<Integer> notShowItemIds = faultItemTimeConfigService.listNotShowItemByTime(itemDIO.getServiceTime());
            if (!CollectionUtils.isEmpty(notShowItemIds)) {
                productFaultItemExcutePriceResultVos = productFaultItemExcutePriceResultVos.stream().filter(e -> !notShowItemIds.contains(e.getItemId())).collect(Collectors.toList());
            }
        }
        List<ItemDRO> dros = productFaultItemExcutePriceResultVos.stream().map(productFaultItemExcutePriceResultVo -> {
            ItemDRO itemDRO = new ItemDRO();
            BeanUtils.copyProperties(productFaultItemExcutePriceResultVo, itemDRO);
            itemDRO.setCategName(productFaultItemExcutePriceResultVo.getBackProductCategTwoName());
            itemDRO.setCategOneName(productFaultItemExcutePriceResultVo.getBackProductCategOneName());
            itemDRO.setTechnologyFee(productFaultItemExcutePriceResultVo.getArtPrice());
            itemDRO.setGuaranteeFee(productFaultItemExcutePriceResultVo.getGuaranteePrice());
            return itemDRO;
        }).collect(Collectors.toList());

        // 特殊服务项
        if (CollectionUtil.isNotNullOrEmpty(itemDIO.getIdList())) {
            List<ProductServiceItemDRO> dro = faultItemBService.listByCategIdList(itemDIO.getIdList(),null);
            List<ItemDRO> specialItemDROS = dro.stream().map(productFaultItemDRO -> {
                ItemDRO itemDRO = new ItemDRO();
                BeanUtils.copyProperties(productFaultItemDRO, itemDRO);
                return itemDRO;
            }).collect(Collectors.toList());

            if (CollectionUtils.isEmpty(dros)) {
                return specialItemDROS;
            } else {
                dros.addAll(specialItemDROS);
            }
        }

        return dros;
    }

    /**
     * 描述:前台产品价格表合并
     *
     * @param
     * @return
     * @auther tanghongjun
     * @since 2020/10/12
     */
    private List<ItemGroupDRO> getQuotationServiceItem(List<ItemDRO> data) {

        List<ItemGroupDRO> priceVOList = new ArrayList<>();

        List<ItemDRO> itemDROList = data;

        Stream<ItemDRO> stream = itemDROList.stream();

        HashMap<Integer, List<ItemDRO>> categMap = stream
                .sorted(Comparator.comparing(ItemDRO::getGroupSort))
                .collect(Collectors.groupingBy(ItemDRO::getFaultCategId, HashMap::new, Collectors.toList()));

        categMap.forEach((categId, categList) -> {

            // 1级 分组
            if (CollectionUtil.isNullOrEmpty(categList)) {
                return;
            }

            String categName = categList.get(0).getFaultCategName();
            ItemGroupDRO priceVO = new ItemGroupDRO(categId, categName, null);
            List<ItemPriceSimpleDRO> serviceItemVOList = Lists.newArrayList();
            priceVO.setServiceItems(serviceItemVOList);

            HashMap<Integer, List<ItemDRO>> itemMap = categList.stream()
                    .sorted(Comparator.comparing(ItemDRO::getItemSort))
                    .collect(Collectors.groupingBy(ItemDRO::getItemId, HashMap::new, Collectors.toList()));

            itemMap.forEach((itemId, itemList) -> {

                // 2级 服务项
                if (CollectionUtil.isNullOrEmpty(itemList)) {
                    return;
                }

                String itemName = itemList.get(0).getGroupName();
                ItemPriceSimpleDRO serviceItemVO = new ItemPriceSimpleDRO();
                serviceItemVO.setItemId(itemId);
                serviceItemVO.setName(itemName);
                List<ProductSimpleDRO> productList = Lists.newArrayList();
                serviceItemVO.setProductList(productList);

                itemList.forEach(product -> {

                    // 3级 产品
                    if (product == null) {
                        return;
                    }
                    ProductSimpleDRO productSimpleDRO = new ProductSimpleDRO();
                    productSimpleDRO.setProductId(product.getProductId());
                    productSimpleDRO.setProductName(product.getItemName());
                    productSimpleDRO.setDesc(product.getDesc());
                    productSimpleDRO.setPrice(product.getPrice());
                    productSimpleDRO.setUnit(product.getUnit());
                    productList.add(productSimpleDRO);
                });
                serviceItemVOList.add(serviceItemVO);
            });


            priceVOList.add(priceVO);
        });

        return priceVOList;
    }
}
